#pragma once
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include<functional>
#include "InetAddr.hpp"

using fun_t= std::function<void(int sockfd,const std::string&,InetAddr&)>;

using namespace LogModel;
class Udpserver
{   
    public:
    Udpserver(uint16_t port,fun_t fun)
    :_sfd(-1),
    _port(port),
    _isruning(false),
    _fun(fun)
    {
        //初始化
        _sfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_sfd<0)
        {
            LOG(LogLevel::FATAL)<<"创套接字失败";
            exit(1);
        }
        LOG(LogLevel::DEBUG)<<"创建成功";
        //创建成功，需要进行bind
        struct sockaddr_in udpserver;
        bzero(&udpserver,sizeof(udpserver));
        udpserver.sin_family=AF_INET;
        udpserver.sin_addr.s_addr=INADDR_ANY;
        //主机->网络
        udpserver.sin_port=htons(_port);

        //bind
        int n = bind(_sfd,(struct sockaddr*)&udpserver,sizeof(udpserver));
        if(n<0)
        {
            LOG(LogLevel::FATAL)<<"绑定失败";
            exit(2);
        }
        LOG(LogLevel::DEBUG)<<"绑定成功";
    }
    void Start()
    {
        _isruning=true;
        while(_isruning)
        {
            //接收来着客户端的消息
            char buff[1024];
            struct sockaddr_in udpclient;//客户端
            socklen_t len=sizeof(udpclient);
            int n = recvfrom(_sfd,buff,sizeof(buff)-1,0,(struct sockaddr*)&udpclient,&len);
            if(n>0)
            {
                InetAddr Id(udpclient);
                buff[n]=0;
                //要实现多人聊天功能，要将接收到的消息转发给所有在线的用户
                //1.用户的信息，ip+port
                _fun(_sfd,buff,Id);
            }

            //返回客户端的信息
            //int m = sendto(_sfd,buff,sizeof(buff),0,(struct sockaddr*)&udpclient,len);
        }
    }
    ~Udpserver()
    {}
    private:
    int _sfd;//套接字描述符
    uint16_t _port;//端口号
    bool _isruning;
    fun_t _fun;
};